﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using SharePointEnforcer.Utilities;

namespace SharePointEnforcer
{
    class EnforcerCommandArgs
    {

        protected enum FilePathType:int
        {
            Unknown = 0,
            Rules=1,
            Handlers=2
        }


        public static EnforcerSettings ProcessArgs(string[] pArgs)
        {
            EnforcerSettings settings = new EnforcerSettings();

            ProcessArgs(settings, pArgs);

            return settings;
        }

        private static void ProcessArgs(EnforcerSettings pSettings, string[] pArgs)
        {
            int iPos = 0;

            while (iPos < pArgs.Length)
            {
                string arg = pArgs[iPos];
                if (IsSwitched(arg) && arg.Length>1)
                {
                    arg = arg.Substring(1);

                    switch(arg.ToLower()) {
                        case "help":
                        case "?":
                            pSettings.HelpRequested = true;
                            break;

                        case "rule":
                        case "rules":
                            ProcessFileArg(pSettings, FilePathType.Rules, pArgs, iPos);
                            break;

                        case "handler":
                        case "handlers":
                            ProcessFileArg(pSettings, FilePathType.Handlers, pArgs, iPos);
                            break;

                        case "test":
                        case "testing":
                        case "noupdate":
                        case "whatif":
                            pSettings.WhatIf = true;
                            break;

                        default :
                            pSettings.HelpNeeded = true;
                            pSettings.UnknownCommands.Add(arg);
                            break;
                    }
                }
                iPos++;
            }
        }

        private static string GetNextArg(string[] pArgs, int iCurrentArg)
        {
            if (iCurrentArg + 1 < pArgs.Length) return pArgs[iCurrentArg + 1];
            return null;
        }


        /// <summary>
        /// Generic handler for arguments that take file paths as parameters
        /// </summary>
        /// <param name="pCurrentArg">the position of the current argument</param>
        private static void ProcessFileArg(EnforcerSettings pSettings, FilePathType pFileType, string[] pArgs, int pCurrentArg)
        {
            string arg = pArgs[pCurrentArg];
            string nextArg = GetNextArg(pArgs, pCurrentArg);

            if (string.IsNullOrEmpty(nextArg))
            {
                pSettings.ErrorMessages.Add(Resources.Enforcer.err_cmdFileNotSpecified, arg);
                return;
            }

            // multiple paths can be included simply by separating them with the characters below
            string[] paths = nextArg.Split(';', ',', '|');

            foreach (string path in paths)
            {
                string fullFilePath = Utilities.EnforcerUtils.Files.Find(path);
                if (string.IsNullOrEmpty(fullFilePath) || !File.Exists(fullFilePath))
                {
                    pSettings.ErrorMessages.Add(Resources.Enforcer.err_cmdFileNotFound, path, arg);
                }
                else
                {
                    AddFilePathToList(pSettings, pFileType, fullFilePath);
                }
            }
        }


        /// <summary>
        /// Adds the path to the proper collection for later processing
        /// </summary>
        /// <param name="pFileType">the type that the path should be added to</param>
        /// <param name="pFilePath">the full path to the file</param>
        private static void AddFilePathToList(EnforcerSettings pSettings, FilePathType pFileType, string pFilePath)
        {
            switch (pFileType)
            {
                case FilePathType.Rules:
                    pSettings.RulesPaths.Add(pFilePath);
                    break;

                case FilePathType.Handlers:
                    pSettings.HandlerPaths.Add(pFilePath);
                    break;

                default:
                    break;
            }
        }
    



        /// <summary>
        /// is it a switched parameter?
        /// </summary>
        /// <param name="pArg">the argument to check</param>
        /// <returns>true if the argument starts with a switch character, false otherwise</returns>
        private static bool IsSwitched(string pArg)
        {
            if (!string.IsNullOrEmpty(pArg))
            {
                if (pArg.StartsWith("-") || pArg.StartsWith("/")) return true;
            }
            return false;

        }
    }
}

